package thread.multi.comuni;

//测试：生产者消费者问题-->管程法

//成员：生产者，消费者，产品，缓冲区
/**
 * 将产品放入缓冲区，通过判断缓冲区数据的数量，达到线程间的通信
 * 1.线程开启后，线程都在执行
 * 2.当消费者线程执行时，如果缓冲区数据为空，消费者线程等待，生产者线程继续
 * 3.当生产者线程执行时，如果缓冲区数据为满，生产者线程等待，消费者线程继续
 * 4.否则，当生产者生产后唤醒消费者，消费者消费后唤醒生产者
 * 其的根本逻辑在于，不存在一种状态，使得消费者和生产者同时等待
 */
public class ProducerCustomer {
    public static void main(String[] args) {
        Synbuffer buffer = new Synbuffer();

        new Producer(buffer).start();
        new Customer(buffer).start();
    }
}

class Producer extends Thread {
    public Synbuffer buffer;

    public Producer(Synbuffer buffer) {
        this.buffer = buffer;
    }

    //生产者生产鸡
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            buffer.push(new Chicken(i));
            System.out.println("生产了第"+i+"只鸡");
        }
    }
}

class Customer extends Thread {
    public Synbuffer buffer;

    public Customer(Synbuffer buffer) {
        this.buffer = buffer;
    }

    //消费者消费鸡
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            int id = buffer.pop().id;
            System.out.println("消费了第"+id+"只鸡");
        }
    }
}

class Chicken {
    public int id;

    public Chicken(int id) {
        this.id = id;
    }
}

//缓冲区
class Synbuffer {
    //buffer容器大小
    public Chicken[] products = new Chicken[10];
    public int count = 0;

    //生产者函数，放入产品
    public synchronized void push(Chicken chicken) {
        //判断，容器存满，需要通知消费者消费，并且生产等待
        if (count == products.length) {
            //代码，消费者消费，生产者等待
            try {
                this.wait();
                System.out.println("产品满了，消费者快来！");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        products[count++] = chicken;
        this.notifyAll();
    }

    //消费者函数，消费产品
    public synchronized Chicken pop() {
        //判断，容器缺空，需要通知生产者生产，并且消费等待
        if (count == 0) {
            //代码，生产者生产，消费者等待
            try {
                this.wait();
                System.out.println("产品空了，生产者快来！");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        count--;
        Chicken chicken = products[count];

        this.notifyAll();
        return chicken;
    }
}